#include "otherFns.h"
#include "evaluationFns.h"

using namespace std;

//--------------------------------------------------------------------------------------
void printGrid(int **theGrid, int sqLen, int grLen, int first, bool **fixed)
{
	//PRINTS THE GRID TO THE SCREEN IN A (USUALLY) NICE WAY
	bool full = true;
	cout<<'\n';
	int r,i, c;
	for(r=0;r<grLen;r++){
		if(r%sqLen==0){ 
			for(i=0;i<grLen+sqLen;i++)
				cout<<"---\t";
			cout<<"|\n";
		}
		for(c=0;c<grLen;c++){
			if(c%sqLen==0) 
				cout<<"|\t";
			if(theGrid[r][c]!=-1){
				if(theGrid[r][c]>=10){
					if(fixed[r][c])	cout<<'('<<convert(theGrid[r][c])<<")\t";
					else cout<<convert(theGrid[r][c])<<'\t';
				}
				else {
					if(fixed[r][c])cout<<'('<<theGrid[r][c]<<")\t";
					else cout<<theGrid[r][c]<<'\t';
				}
			}
			else {
				cout <<"x\t";
				full=false;
			}
		}
		cout<<"|\n";
	}
	for(i=0;i<grLen+sqLen;i++)
			cout<<"---\t";

	if(full){
		int count;
		int *nums = new int [grLen+1];
		if (first==0) for(i=0;i<grLen;i++)nums[i]=i;
		else for(i=1;i<grLen+1;i++)nums[i]=i;
		cout<<"\n Row Scores - ";
		//Go through each row and determine the score
		for(r=0;r<grLen;r++){
			count = 0;
			for(c=0;c<grLen;c++){
				nums[theGrid[r][c]]=-1;
			}
			//count the number of nums not present in the row
			if(first==0){
				for(i=0;i<grLen;i++){
					if(nums[i]!=-1)count++;
				}
				cout<<"r"<<r<<'='<<count<<' ';
			}				
			else{
				for(i=1;i<grLen+1;i++){
					if(nums[i]!=-1)count++;
				}
				cout<<"r"<<r<<'='<<count<<' ';
			}
			//Reset nums Array
			if (first==0) for(i=0;i<grLen;i++)nums[i]=i;
			else for(i=1;i<grLen+1;i++)nums[i]=i;
		}
		cout<<"\n Col Scores - ";
		//Go through each col and determine the score
		for(c=0;c<grLen;c++){
			count = 0;
			for(r=0;r<grLen;r++){
				nums[theGrid[r][c]]=-1;
			}
			//count the number of nums not present in the row
			if(first==0){
				for(i=0;i<grLen;i++){
					if(nums[i]!=-1)count++;
				}
				cout<<"c"<<c<<'='<<count<<' ';
			}				
			else{
				for(i=1;i<grLen+1;i++){
					if(nums[i]!=-1)count++;
				}
				cout<<"c"<<c<<'='<<count<<' ';
			}
			//Reset nums Array
			if (first==0) for(i=0;i<grLen;i++)nums[i]=i;
			else for(i=1;i<grLen+1;i++)nums[i]=i;
		}
		delete [] nums;
	}
	cout<<"\n\n"<<endl;
}

//--------------------------------------------------------------------------------------
double calcInitTemp(int **grid, int sqLen, int grLen, int *rowScores, int *colScores, int first, bool **fixed
#ifdef USE_HEURISTIC_SELECTION_LIBRARY
    , MoveSelector& mhs
#endif
)
{
	//Calculates the initial temperature that we will cool from
	int sampleSize = 100, i, r1, r2, c1, c2, r1Sc,r2Sc,c1Sc,c2Sc;
	int *theArray = new int [sampleSize];
	
	//evaluate the timetable
	theArray[0]=evaluate(grid,sqLen,grLen,rowScores,colScores,first);
	
	//Now do a few moves, and record the variance of the score
	for(i=1; i<sampleSize; i++){
		doMove(grid,fixed,grLen,sqLen,r1,r2,c1,c2
#ifdef USE_HEURISTIC_SELECTION_LIBRARY
            , mhs
#endif
        );
		theArray[i]=reEvaluate(grid,rowScores,colScores,grLen,r1,r2,c1,c2,r1Sc,r2Sc,c1Sc,c2Sc,first);
		undoMove(grid,rowScores,colScores,grLen,r1,r2,c1,c2,r1Sc,r2Sc,c1Sc,c2Sc);
	}

	return(stDev(theArray,sampleSize));
	delete [] theArray;
}

//--------------------------------------------------------------------------------------
double stDev(int *theArray, int len)
{
	//RHYD: I checked this function on the 21/sept/2007 -- 2 years after doing the paper. It works and DOES calculate
	//the standard deviation.
	int tot = 0, totSq = 0, i;
	for(i=0;i<len;i++){
		tot = tot + theArray[i];
		totSq = totSq + (int)(pow(theArray[i],2));
	}
	return(sqrt(  ( (len*totSq)-(pow(tot,2)) ) / double(len*(len-1))  ));
}

//--------------------------------------------------------------------------------------
char convert(int n){
	if(n==10)return 'A';
	else if(n==11)return 'B';
	else if(n==12)return 'C';
	else if(n==13)return 'D';
	else if(n==14)return 'E';
	else if(n==15)return 'F';
	else if(n==16)return 'G';
	else if(n==17)return 'H';
	else if(n==18)return 'I';
	else if(n==19)return 'J';
	else if(n==20)return 'K';
	else if(n==21)return 'L';
	else if(n==22)return 'M';
	else if(n==23)return 'N';
	else if(n==24)return 'O';
	else if(n==25)return 'P';
	else if(n==26)return 'Q';
	else if(n==27)return 'R';
	else if(n==28)return 'S';
	else return '*';
}

